package example.rmi;

import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;

import util.AgregadorRMI;
import util.IPGetter;
import controlador.buzones.Buzon;
import controlador.buzones.BuzonIface;
import controlador.buzones.Mensaje;
import controlador.buzones.MessageTypes;

/**
 * 
 * @author Globex Inc.
 *
 */
public class Dumb {
	
	/**
	 * El buzon de este cliente. Este buzon luego se agrega al registro RMI
	 * para que las aplicaciones que no corren en este ordenador puedan
	 * acceder a el.
	 */
	private BuzonIface _buzon;
	
	public Dumb(int port, String id) throws Exception {
		_buzon = new Buzon();
		// lo de registrar el buzon se puede hacer luego pero he preferido
		// hacerlo aqui
		_buzon.registrar(port, id); 
	}
	
	public BuzonIface getBuzon() {
		return _buzon;
	}
	
	public boolean comprobarMensajes() throws Exception {
		Mensaje msj = _buzon.desencolar();
		boolean ans = false;
		
		if(msj != null) {
			System.out.println("Message received from "+msj.get_source()+" to "+msj.get_target());
			for(String key : msj.get_message().keySet()) {
				System.out.println("\t"+key+": "+msj.get_message().get(key));
			}
			ans = true;
		}
		
		return ans;
	}
	
	/**
	 * 
	 * @param args:
	 * 0 this rmi port
	 * 1 this rmi id
	 * 2 broker host
	 * 3 broker port
	 * 4 broker id
	 * 5 max messages
	 */
	public static void main(String[] args) {
		int localPort = Integer.parseInt(args[0]);
		String localID = args[1];
		String brokerHost = args[2];
		int brokerPort = Integer.parseInt(args[3]);
		String brokerID = args[4];
		int maxMessages = Integer.parseInt(args[5]);
		
		try {
			Dumb tester = new Dumb(localPort, localID);
			
			/* Con este bloque de aqui obtenemos el buzon del broker y lo usamos como si fuese un
			 * objeto local.
			 */
			System.out.println("Getting mailbox at "+brokerHost+":"+brokerPort+"/"+brokerID);
			BuzonIface otro = null;
			int tries = 1;
			
			// hacemos peticiones para obtener el buzon hasta que nos lo obtengamos
			while(otro == null) {
				System.out.println("Try "+(tries++));
				try {
					otro = (BuzonIface) AgregadorRMI.obtenerRemoto(brokerHost, brokerPort, brokerID);
				} catch(Exception e){
					e.printStackTrace();
				}
				
				Thread.sleep(500);
			}
			
			System.out.println("Getting mailbox at "+brokerHost+":"+brokerPort+"/"+brokerID);
			
			// con este bloque enviamos la peticon al broker para que obtenga nuestro buzon
			// de esta forma podra enviarnos mensajes. Podriamos usar el buzon del broker
			// que hemos obtenido para dejarle mensajes pero seria un lio porque en ese caso
			// tendriamos que comprobar para quien es el mensaje
			System.out.println("Asking broker to get my mailbox");
			String myIP = IPGetter.getIP();
			
			Mensaje msj = new Mensaje();
			msj.set_source(localID);
			msj.set_target(brokerID);
			// este tipo de mensaje es el que provoca que el broker agrege este
			// buzon a la lista de buzones a los que puede enviar mensajes
			msj.set_type(MessageTypes.BEFRIEND);
			
			HashMap<String, String> content = new HashMap<String, String>();
			content.put("registry:path", localID);
			content.put("registry:host", myIP);
			content.put("registry:port", ""+localPort);
			msj.set_message(content);
			// esto envia el mensaje
			otro.encolar(msj);
			
			// recibimos mensajes hasta el maximo establecido
			int receiveCount = 0;
			while(receiveCount < maxMessages) {
				if(tester.comprobarMensajes())
					receiveCount++;
			}
			
			System.out.println("Asking broker stop sending me crap");
			
			msj = new Mensaje();
			msj.set_source(localID);
			msj.set_target(brokerID);
			msj.set_type(MessageTypes.UNFRIEND);
			
			otro.encolar(msj);
			
			System.out.println("Unfriend petition sent");
			System.out.println("Message received before unfriending and not processed");
			while(tester.comprobarMensajes());
			
			System.out.println("And now I quit. Bye!");
			
			//public void exit() throws RemoteException {
			    try{
			        // Unregister ourself
			        Naming.unbind("//localhost:"+localPort+"/"+localID);
			        // Unexport; this will also remove us from the RMI runtime
			        UnicastRemoteObject.unexportObject(tester._buzon, true);
			    }
			    catch(Exception e){}
			//}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
